package main
// +----------------------------------------------------------------------
// | Update: 2022-11-03 10:24
// +----------------------------------------------------------------------
// | Author: Kerindax <1482152356@qq.com>
// +----------------------------------------------------------------------
// | Project Url: https://gitee.com/kerindax/UyghurCharUtils
// +----------------------------------------------------------------------
import (
    "regexp"
    "strings"
)
//补充对象
type regstr string;
//补充函数
func (source regstr) toString() string{
    return string(source);
}
func (source regstr) reverse() regstr {
    runes := []rune(source)
    for from, to := 0, len(runes)-1; from < to; from, to = from+1, to-1 {
        runes[from], runes[to] = runes[to], runes[from]
    }
    return regstr(runes)
}
func (source regstr) replaceAll(rang string, repl func(string,[]string) string) regstr{
    reg := regexp.MustCompile(rang)
    return regstr(reg.ReplaceAllStringFunc(source.toString(),func(str string) string{
        arg := []rune(str);
        var arr = []string{};
        for _,item := range arg{
            arr = append(arr,string(item));
        }
        return repl(str,arr);
    }))
}

type UyghurCharObject struct {};
func (source regstr) trim() regstr{
    return regstr(strings.Trim(source.toString(), "  "));
}
// 双目字对象
type SpecialObject struct {
    basic []rune;
    extend []rune;
    link []rune;
}

const BASIC = 0; //基本区形式  A
const ALONE = 1; //单独形式    A
const HEAD  = 2; //头部形式    A_
const CENTR = 3; //中部形式   _A_
const REAR  = 4; //后部形式   _A
// 双字母列表
var special =[]SpecialObject{
    SpecialObject{
        basic: []rune{ 0x644, 0x627 },
        extend: []rune{ 0xfefc },
        link: []rune{ 0xfee0, 0xfe8e },
    },
    SpecialObject{
        basic: []rune{ 0x644, 0x627 },
        extend: []rune{ 0xfefb },
        link: []rune{ 0xfedf, 0xfe8e },
    },
};
// 单字母列表
var charCode map[string][]string = map[string][]string{};
//数字转换对应的字母
func (self UyghurCharObject) fromCharCode(number rune) string {
    return string(number);
}

func UyghurCharUtils() UyghurCharObject {
    self := UyghurCharObject{}
    /**
        * 基本码, 单独形式, 头部形式, 中部形式, 后部形式]
        * [  A  ,     A   ,    A_   ,   _A_  ,   _A   ]
        */
    for _,row :=range [][]rune{
        {0x626, 0xfe8b, 0xfe8b, 0xfe8c, 0xfe8c}, // 1 --- 00-Hemze
        {0x627, 0xfe8d, 0xfe8d, 0xfe8e, 0xfe8e}, // 0 --- 01-a
        {0x6d5, 0xfee9, 0xfee9, 0xfeea, 0xfeea}, // 0 --- 02-:e
        {0x628, 0xfe8f, 0xfe91, 0xfe92, 0xfe90}, // 1 --- 03-b
        {0x67e, 0xfb56, 0xfb58, 0xfb59, 0xfb57}, // 1 --- 04-p
        {0x62a, 0xfe95, 0xfe97, 0xfe98, 0xfe96}, // 1 --- 05-t
        {0x62c, 0xfe9d, 0xfe9f, 0xfea0, 0xfe9e}, // 1 --- 06-j
        {0x686, 0xfb7a, 0xfb7c, 0xfb7d, 0xfb7b}, // 1 --- 07-q
        {0x62e, 0xfea5, 0xfea7, 0xfea8, 0xfea6}, // 1 --- 08-h
        {0x62f, 0xfea9, 0xfea9, 0xfeaa, 0xfeaa}, // 0 --- 09-d
        {0x631, 0xfead, 0xfead, 0xfeae, 0xfeae}, // 0 --- 10-r
        {0x632, 0xfeaf, 0xfeaf, 0xfeb0, 0xfeb0}, // 0 --- 11-z
        {0x698, 0xfb8a, 0xfb8a, 0xfb8b, 0xfb8b}, // 0 --- 12-:zh
        {0x633, 0xfeb1, 0xfeb3, 0xfeb4, 0xfeb2}, // 1 --- 13-s
        {0x634, 0xfeb5, 0xfeb7, 0xfeb8, 0xfeb6}, // 1 --- 14-x
        {0x63a, 0xfecd, 0xfecf, 0xfed0, 0xfece}, // 1 --- 15-:gh
        {0x641, 0xfed1, 0xfed3, 0xfed4, 0xfed2}, // 1 --- 16-f
        {0x642, 0xfed5, 0xfed7, 0xfed8, 0xfed6}, // 1 --- 17-:k
        {0x643, 0xfed9, 0xfedb, 0xfedc, 0xfeda}, // 1 --- 18-k
        {0x6af, 0xfb92, 0xfb94, 0xfb95, 0xfb93}, // 1 --- 19-g
        {0x6ad, 0xfbd3, 0xfbd5, 0xfbd6, 0xfbd4}, // 1 --- 20-:ng
        {0x644, 0xfedd, 0xfedf, 0xfee0, 0xfede}, // 1 --- 21-l
        {0x645, 0xfee1, 0xfee3, 0xfee4, 0xfee2}, // 1 --- 22-m
        {0x646, 0xfee5, 0xfee7, 0xfee8, 0xfee6}, // 1 --- 23-n
        {0x6be, 0xfbaa, 0xfbac, 0xfbad, 0xfbab}, // 1 --- 24-:h
        {0x648, 0xfeed, 0xfeed, 0xfeee, 0xfeee}, // 0 --- 25-o
        {0x6c7, 0xfbd7, 0xfbd7, 0xfbd8, 0xfbd8}, // 0 --- 26-u
        {0x6c6, 0xfbd9, 0xfbd9, 0xfbda, 0xfbda}, // 0 --- 27-:o
        {0x6c8, 0xfbdb, 0xfbdb, 0xfbdc, 0xfbdc}, // 0 --- 28-v
        {0x6cb, 0xfbde, 0xfbde, 0xfbdf, 0xfbdf}, // 0 --- 29-w
        {0x6d0, 0xfbe4, 0xfbe6, 0xfbe7, 0xfbe5}, // 1 --- 30-e
        {0x649, 0xfeef, 0xfbe8, 0xfbe9, 0xfef0}, // 1 --- 31-i
        {0x64a, 0xfef1, 0xfef3, 0xfef4, 0xfef2}, // 1 --- 32-y

        {0x6c5, 0xfbe0, 0xfbe0, 0xfbe1, 0xfbe1}, // 0 --- kz o_
        {0x6c9, 0xfbe2, 0xfbe2, 0xfbe3, 0xfbe3}, // 0 --- kz o^
        {0x62d, 0xfea1, 0xfea3, 0xfea4, 0xfea2}, // 1 --- kz h
        {0x639, 0xfec9, 0xfecb, 0xfecc, 0xfeca}, // 1 --- kz c
    }{
        list := []string{};
        for _,el := range row{
            list = append(list,self.fromCharCode(el));
        }
        for _,item := range list{
            if _, ok := charCode[item]; !ok {
                charCode[item] = list;
            }
        }
    }
    return self;
}
/**
* 基本区   转换   扩展区
* @param source
* 要转换的内容
* @return 
* 已转换的内容
*/
func (self UyghurCharObject) Basic2Extend(source string) string {
    //转换范围；不包含哈语的0x0621字母,问号,双引号和Unicode区域的符号
    convertRang := "[\u0622-\u064a\u0675-\u06d5]+";
    //分割范围，有后尾的字符表达式
    suffixRang := "[^\u0627\u062F-\u0632\u0648\u0688-\u0699\u06C0-\u06CB\u06D5]";
    return regstr(source).replaceAll(convertRang,func(word string,_ []string) string{
        returns := regstr(word).replaceAll(suffixRang,func(ch string,_ []string) string{
                return ch + "  ";
            }).trim().replaceAll("^(\\S)($|\\S)",func(_ string,m []string)string {
                m[0] = self.getChar(m[0], ALONE);
                return strings.Join(m,"");
            }).replaceAll("(\\S)(\\S)($|\\S)",func(_ string,m []string)string {
                m[1] = self.getChar(m[1], ALONE);
                return strings.Join(m,"");
            }).replaceAll("(\\S|^)(\\S)\\s",func(_ string,m []string)string {
                m[len(m) - 2] = self.getChar(m[len(m) - 2], HEAD);
                return strings.Trim(strings.Join(m,""),"  ");
            }).replaceAll("\\s(\\S)\\s",func(_ string,m []string)string {
                m[1] = self.getChar(m[1], CENTR);
                return strings.Trim(strings.Join(m,""),"  ");
            }).replaceAll("\\s(\\S)(\\S|$)",func(_ string,m []string)string {
                m[1] = self.getChar(m[1], REAR);
                return strings.Trim(strings.Join(m,""),"  ");
            }).toString();
        return self.extendLa(returns);
    }).toString();
}
/**
* 扩展区   转换   基本区
* @param source
* 要转换的内容
* @return 
* 已转换的内容
*/
func (self UyghurCharObject) Extend2Basic(source string) string {
    //扩展区范围；FB50-FDFF ->区域A    FE70-FEFF -> 区域B
    extendRang := "[\ufb50-\ufdff\ufe70-\ufeff]";
    return regstr(self.basicLa(source)).replaceAll(extendRang,func(ch string,_ []string) string{
        return self.getChar(ch, BASIC);
    }).toString();
}
/**
* 基本区  转换   反向扩展区
* @param source
* 要转换的内容
* @return
* 已转换的内容
*/
func (self UyghurCharObject) Basic2RExtend(source string) string {
    return self.reverseAscii(self.reverseSubject(self.Basic2Extend(source)));
}
/**
* 反向扩展区   转换   基本区
* @param source
* 要转换的内容
* @return
* 已转换的内容
*/
func (self UyghurCharObject) RExtend2Basic(source string) string {
    return self.Extend2Basic(self.reverseSubject(self.reverseAscii(source)));
}
/**
* 音节索引
*/
func (self UyghurCharObject) BasicSyllable(source string) string {
     //音节切开专用，取韵母 
     finalsRang := "([\u0627\u06d5\u0648\u06c7\u06c6\u06c8\u06d0\u0649\u06c9\u06c5])([^\u0627\u06d5\u0648\u06c7\u06c6\u06c8\u06d0\u0649\u06c9\u06c5]+)([\u0627\u06d5\u0648\u06c7\u06c6\u06c8\u06d0\u0649\u06c9\u06c5])"; 
     return regstr(source).replaceAll("[^\\s]+", func(word string,_ []string) string{
        return regstr(word).replaceAll(finalsRang, func(_ string,m []string) string{
            var sb string;
            for index,item := range m{
                if len(m) / 2 == index{
                    sb += " ";
                }
                sb += item;
            }
            return sb;
        }).toString();
    }).toString();
    return source;
}
/**
* Ascii区反转
*/
func (self UyghurCharObject) reverseAscii(source string) string {
    //特助转换区，扩展区反向转换的时候需要替换
    symbolRang := "[}{><»«\\)\\(\\]\\[]";
    var symbolList = map[string]string{
        ")": "(",
        "(": ")",
        "]": "[",
        "[": "]",
        "}": "{",
        "{": "}",
        ">": "<",
        "<": ">",
        "»": "«",
        "«": "»",
    };
    // //不包含扩展区中部包含空格字符集；FB50-FDFF ->区域A    FE70-FEFF -> 区域B
    notExtendRang := "[^\ufb50-\ufdff\ufe70-\ufeff\\s]+(\\s[^\ufb50-\ufdff\ufe70-\ufeff\\s]+)*";
    return regstr(source).replaceAll(notExtendRang, func(word string,_ []string) string{
        return regstr(word).reverse().replaceAll(symbolRang, func(ch string,_ []string) string{
            if _, ok := symbolList[ch]; ok {
                return symbolList[ch];
            }else{
                return ch;
            }
        }).toString();
    }).toString();
    return source;
}
/**
* 对象反转
*/
func (self UyghurCharObject) reverseSubject(str string) string {
    return regstr(str).replaceAll(".+", func(subject string,_ []string) string{
        return regstr(subject).reverse().toString();
    }).toString();
}
/**
* 获取对应字母
*/
func (self UyghurCharObject) getChar(ch string, index int) string {
    return charCode[ch][index];
}
/**
* La字母转换扩展区
*/
func (self UyghurCharObject) extendLa(source string) string {
    for _,item := range special{
        source = strings.Replace(source, self.getString(item.link), self.getString(item.extend), -1);
    }
    return source;
}
/**
* La字母转换基本区
*/
func (self UyghurCharObject) basicLa(source string) string {
    for _,item := range special{
        source = strings.Replace(source, self.getString(item.extend), self.getString(item.basic), -1);
    }
    return source;
}
/**
* 双目字母转换字符串
*/
func (self UyghurCharObject) getString(value []rune) string {
    return string(value);
}
